home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / overview / optimization tn demos / cacheline optimizer / cache.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  4.5 KB  |  166 lines

  1. /*
  2.     File:         cache.c
  3.  
  4.     Contains:     Cache Optimizer
  5.     
  6.     Assumptions: This code assumes that you are making aligned accesses to the cache,
  7.                  and that your stride value maintains this alignment.  Because of this, I don't 
  8.                  deal with cases where your reads would overlap multiple cache blocks.
  9.  
  10.     Written by:     Tim Carroll
  11.  
  12.     Copyright:     Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved.
  13.  
  14.                  You may incorporate this Apple sample source code into your program(s) without
  15.                  restriction. This Apple sample source code has been provided "AS IS" and the
  16.                  responsibility for its operation is yours. You are not permitted to redistribute
  17.                  this Apple sample source code as "Apple sample source code" after having made
  18.                  changes. If you're going to re-distribute the source, we require that you make
  19.                  it clear in the source that the code was descended from Apple sample source
  20.                  code, but that you've made changes.
  21.  
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <math.h>
  28. #include <sioux.h>
  29.  
  30. char gTextBuffer[512];
  31.  
  32. typedef struct {
  33.     int size;                // number of lines in each cache way
  34.     int associativity;        // number of ways in the cache
  35.     int highMask;            // mask range to determine which block is used.
  36.     int lowMask;
  37. } CacheDescription;
  38.  
  39. const int numberCaches = 3;
  40. const unsigned long unusedTag = 0xFFFFFFFFUL;
  41. const unsigned long maskOnes = 0xFFFFFFFFUL;
  42.  
  43. char *cacheStrings[3] =
  44. {
  45.     "L1 Cache",
  46.     "L2 Cache",
  47.     "TLB Entries"
  48. };
  49.     
  50. /* These numbers are based on an iMac with 512K of cache */
  51.     
  52. CacheDescription cache [3] =
  53. {
  54.     128,8,20,26,  /* L1 */
  55.     4096,2,14,25, /* L2 */
  56.     64,2,14,19      /* TLB */
  57. };
  58.  
  59. unsigned long tags[4096][8]; // array large enough to hold all tag data for any cache.
  60.  
  61.  
  62. void DumpCacheTable (int stride, char *name, CacheDescription *cache);
  63.  
  64. int main(void)
  65. {    
  66.     int stride, loop;
  67.  
  68.     printf ("Welcome to the cacheline tester.\n");
  69.     printf ("Given a stride value, this program simulates walking through memory\n");
  70.     printf ("and will give you an indication of how many cachelines you will be\n");
  71.     printf ("using in the L1 and L2 caches.  It also gives an idea of the virtual\n");
  72.     printf ("memory performance by measuring how many TLB entries your code will\n");
  73.     printf ("use\n\n");
  74.     
  75.     while (1)
  76.     {
  77.         printf ("Enter the stride value you wish to test, or 0 to end:\n");
  78.     
  79.         gets( gTextBuffer );
  80.         stride = atoi( gTextBuffer );
  81.     
  82.         if (stride < 1)
  83.             break;
  84.         else
  85.         {
  86.             for (loop = 0; loop < numberCaches; loop++)
  87.                 DumpCacheTable(stride, cacheStrings[loop], &(cache[loop]));
  88.         }
  89.     };
  90.     
  91.     return 0;
  92. }
  93.  
  94. void DumpCacheTable (int stride, char *name, CacheDescription *cache)
  95. {
  96.     unsigned int address, block, tag;
  97.     int loop, loop2;
  98.     
  99.     int size            = cache->size;
  100.     int associativity    = cache->associativity;
  101.     int highMask        = cache->highMask;
  102.     int lowMask            = cache->lowMask;
  103.  
  104.     int    iterations, cachelines;
  105.     float cacheUtilization;
  106.     
  107.     /* Initialize all the cache tags to our invalid value */
  108.     for (loop = 0; loop < size; loop++)
  109.     {
  110.         for (loop2 = 0; loop2 < associativity; loop2++)
  111.         {
  112.             tags[loop][loop2] = unusedTag;
  113.         }
  114.     }
  115.     
  116.     /* We start to walk through the data at address 0.  We act as if we are
  117.        just touching the byte at the address -- this allows us to ignore
  118.        misalignment cases, where a quantity straddles two cachelines. 
  119.        
  120.        We walk the list until we hit a cacheline which has all ways already
  121.        filled with valid data.  From this point on, we would be throwing data
  122.        out of this cache.
  123.     */
  124.        
  125.     address = 0;
  126.     iterations = 0;
  127.     cachelines =0;
  128.  
  129.     do
  130.     {
  131.         /* calculate the cache block and tag value for the current address */
  132.         block = (address >> (31-lowMask)) & (maskOnes >> (31+highMask-lowMask));
  133.         tag = (address >> (32-highMask));
  134.  
  135.         /* determine if we've already put this tag into the block, or if there is
  136.            an open tag */
  137.            
  138.         for (loop = 0; loop < associativity; loop++)
  139.         {
  140.             if (tags[block][loop] == tag)
  141.             {
  142.                 /* tag is already in list, continue */
  143.                 address += stride;
  144.                 iterations += 1;
  145.                 break;
  146.             }
  147.             
  148.             if (tags[block][loop] == unusedTag)
  149.             {
  150.                 /* empty block, add to list */
  151.                 tags[block][loop] = tag;
  152.                 cachelines += 1;
  153.                 address += stride;
  154.                 iterations += 1;
  155.                 break;
  156.             }
  157.         }
  158.         /* if the for loop falls through, we are done, and fall through here as well */
  159.         
  160.     } while (loop < associativity);
  161.     
  162.     cacheUtilization = (float) cachelines / (float) ( associativity * size) * 100.0;
  163.     printf ("For the %s, this stride will evict your own data after %d iterations, \nusing %.0f percent of the cache\n\n",
  164.                 name, iterations, cacheUtilization);
  165. }
  166.